package com.cwh.taskcenter.reward.strategy.impl;

import cn.hutool.core.date.DateUtil;
import com.cwh.taskcenter.domain.reward.gateway.PointAccountGateWay;
import com.cwh.taskcenter.domain.reward.gateway.RewardRecordGateWay;
import com.cwh.taskcenter.domain.reward.gateway.UserPointRecordGateWay;
import com.cwh.taskcenter.domain.reward.model.PointAccount;
import com.cwh.taskcenter.domain.reward.model.RewardRecord;
import com.cwh.taskcenter.domain.reward.model.RewardStatus;
import com.cwh.taskcenter.domain.reward.model.UserPointRecord;
import com.cwh.taskcenter.reward.strategy.RewardStrategy;
import com.cwh.taskcenter.reward.dto.GrantRewardCmd;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;


/**
 * @author cwh
 */
@Slf4j
@Component("POINT")
@RequiredArgsConstructor
public class PointsRewardStrategy implements RewardStrategy {

    @Autowired
    private PointAccountGateWay pointAccountGateWay;

    @Autowired
    private UserPointRecordGateWay userPointRecordGateWay;

    @Autowired
    private RewardRecordGateWay rewardRecordGateWay;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean grantReward(GrantRewardCmd req) {
        // 1. 创建奖励记录
        RewardRecord rewardRecord = createRewardRecord(req);
        rewardRecordGateWay.save(rewardRecord);

        // 2. 处理积分账户
        PointAccount pointAccount = getOrCreatePointAccount(req.getUserId());
        Long changePoint = Long.parseLong(req.getRewardValue());

        // 3. 更新积分账户
        pointAccount.addPoints(changePoint);
        pointAccountGateWay.saveOrUpdate(pointAccount);

        // 4. 创建积分记录
        UserPointRecord userPointRecord = createUserPointRecord(req, pointAccount, changePoint);
        userPointRecordGateWay.save(userPointRecord);
        return true;
    }

    private RewardRecord createRewardRecord(GrantRewardCmd req) {
        return RewardRecord.builder()
                .userId(req.getUserId())
                .taskId(req.getTaskId())
                .userTaskId(req.getUserTaskId())
                .rewardType(req.getRewardType())
                .rewardValue(req.getRewardValue())
                .rewardStatus(RewardStatus.GRANTED.getValue())
                .claimTime(LocalDateTime.now())
                .expireTime(DateUtil.parseLocalDateTime(req.getRewardExpireTime()))
                .build();
    }

    private PointAccount getOrCreatePointAccount(Long userId) {
        PointAccount account = pointAccountGateWay.findNormalByUserId(userId);
        if (account == null) {
            return PointAccount.createNewAccount(userId);
        }
        return account;
    }

    private UserPointRecord createUserPointRecord(GrantRewardCmd req, PointAccount account, Long changePoint) {
        return UserPointRecord.builder()
                .userId(req.getUserId())
                .bizId(req.getBizId())
                .bizType(req.getBizType())
                .title(req.getTitle())
                .desc(req.getRewardDesc())
                .changePoint(changePoint)
                .totalPoint(account.getTotalPoint())
                .build();
    }


}
